//--------------------------------------------------------------------------------
// This file is a portion of the D2D1Renderer.  It is distributed
// under the MIT License, available in the root of this distribution and 
// at the following URL:
//
// http://www.opensource.org/licenses/mit-license.php
//
// Copyright (c) Mirco Timmermann
//
//--------------------------------------------------------------------------------
#include "TabContainer.h"
#include "..\ScrollBar.h"

TabContainer::TabContainer(int x, int y, int width, int height) : DisplayObjectContainer(x, y, width, height) {
	_tabWidth = 80;
	_invert = false;
	tabLabelContainerAutoWidth = true; //if the complete area of the tab labels is hitarea, or only where tabs are.
	_tabHeight = 20;
	_tabDistance = 2;

	_currentSelectedTab = 0;
	_mouseOverTabIndex = -1;

	_tabLabelContainer = new DisplayObjectContainer(0, -_tabHeight, _width, _tabHeight);
	_tabLabelContainer->addEventListener(MouseEvent::MOUSE_DOWN0, std::bind(&TabContainer::ON_MOUSE_DOWN0_tabLabelContainer, this, std::placeholders::_1));
	_tabLabelContainer->addEventListener(MouseEvent::MOUSE_MOVE, std::bind(&TabContainer::ON_MOUSE_MOVE_tabLabelContainer, this, std::placeholders::_1));
	_tabLabelContainer->addEventListener(MouseEvent::MOUSE_OUT, std::bind(&TabContainer::ON_MOUSE_OUT_tabLabelContainer, this, std::placeholders::_1));

	DisplayObjectContainer::addChild(_tabLabelContainer);

#ifdef _DEBUG
	this->name = "D2::TabContainer";
#endif
}

TabContainer::~TabContainer(void) {
	
}

void TabContainer::ON_MOUSE_DOWN0_tabLabelContainer(const Event &event) {
	const MouseEvent& mouseEvent = *(MouseEvent*)(&event);

	D2D1_POINT_2F point = _tabLabelContainer->globalToLocal(mouseEvent._stageX, mouseEvent._stageY);
        
	int tab_index = GetTabIndexByPosition(point.x, point.y);
	if(tab_index != -1) {
		Tab* tab = _tabs[tab_index];
		SelectTab(tab);
	}
}

void TabContainer::ON_MOUSE_MOVE_tabLabelContainer(const Event &event) {
	const MouseEvent& mouseEvent = *(MouseEvent*)(&event);

	D2D1_POINT_2F point = _tabLabelContainer->globalToLocal(mouseEvent._stageX, mouseEvent._stageY);
        
	int tab_index = GetTabIndexByPosition(point.x, point.y);
	_mouseOverTabIndex = tab_index;
}

void TabContainer::ON_MOUSE_OUT_tabLabelContainer(const Event &event) {
	_mouseOverTabIndex = -1;
}

/* @Override
*
*/
bool TabContainer::Draw(Direct2DContext* ctx, D2D1::Matrix3x2F* mtx) {
	DrawContainerForm(ctx);
	DrawTabs(ctx);

	DisplayObjectContainer::Draw(ctx, mtx);

	return true;
}

void TabContainer::DrawContainerForm(Direct2DContext* ctx) {
	//ctx->_disableCamera = true;

	ctx->SetFillStyle(0.2f, 0.2f, 0.2f);

	ctx->rect(0, 0, _width, _height);
	ctx->fill();

	//ctx->_disableCamera = false;
}

void TabContainer::DrawTabs(Direct2DContext* ctx) {
	//ctx->_disableCamera = true;

	if(tabLabelContainerAutoWidth) {
		calculateTabContainerTransform();
	}

	for(int i = _tabs.size()-1; i >= 0; i--) {
		Tab* tab = _tabs[i];

		int tab_x = 0;
        if(_invert) {
			tab_x = (_width - _tabWidth) - (i*(_tabWidth + _tabDistance));
		} else {
			tab_x = i*(_tabWidth + _tabDistance);
		}

		//draw the label.
		//ctx->font = "10pt Calibri";
        
		if(tab->highlight) {
			ctx->SetFillStyle(0.8f, 0.8f, 0.8f);
		} else {
			if(i == _mouseOverTabIndex) {
				ctx->SetFillStyle(0.6f, 0.6f, 0.6f);
			} else {
				ctx->SetFillStyle(0.4f, 0.4f, 0.4f);
			}
		}

		//draw the tab.
		ctx->rect(tab_x, -_tabHeight, _tabWidth, _tabHeight);
		ctx->fill();
            
		int textWidth = ctx->measureText(tab->name).width;
		int textHeight = ctx->measureText("M").width*1.2;
        
		ctx->SetStrokeStyle(1.0f, 1.0f, 1.0f);
		ctx->fillText(tab->name, tab_x + _tabWidth/2 - textWidth/2, -_tabHeight + 0); //-_tabHeight + (textHeight));
	}

	//ctx->_disableCamera = false;
}

///

void TabContainer::calculateTabContainerTransform() {
	///*
	_tabLabelContainer->_width = _tabs.size()*(_tabWidth + _tabDistance);
        
	if(_invert) {
		_tabLabelContainer->_x = _width - _tabLabelContainer->_width;
	}
	//*/
}

///

int TabContainer::GetTabIndexByPosition(int x, int y) {
	int step = _tabWidth + _tabDistance;
	int index = -1;

	//clamp the time area.
	if(_invert) {
		if(x > _width) x = _width;
		if(x < (_width - (_tabs.size()*step))) return -1; //point.x = this._tabs.length*step;
            
		index = floor((_width - x)/step);
	} else {
		if(x < 0) x = 0;
		if(x > (_tabs.size()*step)) return -1; //point.x = this._tabs.length*step;
            
		index = floor(x/step);
	}

	return index;
}

///

/*
void TabContainer::OnMouseDown0(const MouseEvent &e) {
	
}
*/

///

TabContainer::Tab* TabContainer::AddTab(std::string name) {
	Tab* tab = new Tab(name, _width, _height);
	_tabs.push_back(tab);

	if(tabLabelContainerAutoWidth) {
		calculateTabContainerTransform();
	}

	return tab;
}

TabContainer::Tab* TabContainer::AddTabAt(std::string name, int index) {
	Tab* tab = new Tab(name, _width, _height);
	_tabs.insert(_tabs.begin() + index, tab);

	if(tabLabelContainerAutoWidth) {
		calculateTabContainerTransform();
	}

	return tab;
}

void TabContainer::RemoveTab(Tab* tab) {
	for(int i = _tabs.size()-1; i >= 0; i--) {
		Tab* currentTab = _tabs.at(i);
		if(currentTab == tab)  {
			_tabs.erase(_tabs.begin() + i);
		}
	}
}

void TabContainer::RemoveTabAt(int index) {
	if(index < 0 || index >= _tabs.size()) return;

	_tabs.erase(_tabs.begin() + index);
}

void TabContainer::RemoveTabByName(std::string name) {
	for(int i = _tabs.size()-1; i >= 0; i--) {
		Tab* currentTab = _tabs.at(i);
		if(currentTab->name == name)  {
			_tabs.erase(_tabs.begin() + i);
		}
	}
}

TabContainer::Tab* TabContainer::SelectTab(Tab* tab) {
	if(tab != 0 && tab == _currentSelectedTab) return 0;

	if(_currentSelectedTab != 0) {
		_currentSelectedTab->highlight = false;
		DisplayObjectContainer::removeChild(_currentSelectedTab->container);
	}

	if(tab != 0) {
		tab->highlight = true;
		DisplayObjectContainer::addChild(tab->container);
	}

	_currentSelectedTab = tab;

	return tab;
}

TabContainer::Tab* TabContainer::SelectTabAt(int index) {
	if(!(index >= 0 && index < _tabs.size())) return 0;

	return SelectTab(_tabs[index]);
}

TabContainer::Tab* TabContainer::SelectTabByName(std::string name) {
	Tab* tab = GetTabByName(name);
	return SelectTab(tab);
}

int TabContainer::GetTabIndexByName(std::string name) {
	for(int i = _tabs.size()-1; i >= 0; i--) {
		Tab* currentTab = _tabs.at(i);
		if(currentTab->name == name)  {
			return i;
		}
	}
	return -1;
}

TabContainer::Tab* TabContainer::GetTabByName(std::string name) {
	for(int i = _tabs.size()-1; i >= 0; i--) {
		Tab* currentTab = _tabs.at(i);
		if(currentTab->name == name)  {
			return currentTab;
		}
	}
	return 0;
}
